from lib.websocket import client
import asyncio
import json
from utils import device,wlan
from lib.config.index import websocket_config, get_all_configs
from lib.log.index import websocket_logger

ws_client = client.AsyncWebsocketClient()


def create_event_buf(type, content, isBinary = False):
    configs = get_all_configs()
    info = {
        "device_info": device.get_info()
    }
    info.update(configs)
    event = {
        "type": type,
        "content": content,
        "device_id": device.get_id(),
        "info": info,
    }

    if not isBinary:
        return json.dumps(event)

    return bytes(json.dumps(event), "utf-8")


ws_url = websocket_config.get_url()
ws_headers = []

async def connect(headers = []):
    global ws_client, ws_url, ws_headers

    ws_headers = [
        ("Device-Id", wlan.get_ifconfig("mac")),
        ("Client-Id", device.get_id()),
    ]
    ws_headers += headers
    
    if await ws_client.open():
        return
    if websocket_config.is_debug():
        print("ws connect remote: ", ws_url)
    try:
        await ws_client.handshake(ws_url, ws_headers)
        device.update_net_info()
    except Exception as e:
        websocket_logger.log("error", str(e))
        if websocket_config.is_debug():
            print("ws connect err: ", e)
            await reconnect()


async def reconnect():
    global ws_client, ws_url
    await ws_client.close()
    if websocket_config.is_debug():
        print("ws try reconnect: ", ws_url)
    try:
        is_open = await ws_client.handshake(ws_url, ws_headers)
        if not is_open:
            websocket_logger.log("info", "reboot")
            device.reboot()
    except Exception as e:
        websocket_logger.log("error", str(e))
        if websocket_config.is_debug():
            print("ws reconnect err: ", e)
            await asyncio.sleep(3)
            await reconnect()


async def close():
    global ws_client
    try:
        await ws_client.close()
    except Exception as e:
        websocket_logger.log("error", str(e))
        if websocket_config.is_debug():
            print("ws close err: ", e)


async def heart_beat():
    global ws_client
    if not await ws_client.open():
        await reconnect()
    event = create_event_buf("heartbeat", "ping")
    try:
        # websocket_logger.log("heartbeat", str(event))
        await ws_client.send(event)
    except Exception as e:
        websocket_logger.log("error", str(e))
        if websocket_config.is_debug():
            print("ws heart beat err: ", e)
        await reconnect()


async def send_msg(content):
    global ws_client
    if not await ws_client.open():
        await reconnect()
    event = create_event_buf("msg", content)
    try:
        websocket_logger.log("info", str(event))
        await ws_client.send(event)
    except Exception as e:
        websocket_logger.log("error", str(e))
        if websocket_config.is_debug():
            print("ws send msg err: ", e)
        await reconnect()


async def send_data(buf):
    global ws_client
    if not await ws_client.open():
        await reconnect()
    try:
        await ws_client.send(buf)
    except Exception as e:
        websocket_logger.log("error", str(e))
        if websocket_config.is_debug():
            print("ws send msg err: ", e)


async def read():
    global ws_client
    try:
        if not await ws_client.open():
            await reconnect()
        data = await ws_client.recv()
        if data is None:
            await reconnect()
        if websocket_config.is_debug():
            print("ws recv debug: ", data)
        return data
    except Exception as e:
        websocket_logger.log("error", str(e))
        if websocket_config.is_debug():
            print("ws read err: ", e)
        await reconnect()


async def demo():
    global ws_client
    await connect()
    while True:
        await heart_beat()
        data = await read()
        print(data)
        await asyncio.sleep(5)


if __name__ == "__main__":
    asyncio.run(demo())
